/*
 * CommandControl ist eine prototypische IP-Fersteuerung für ein Fahrzeug, das 
 * mit dem Arduino (Receiver) gesteuert wird.  Ziel war es, den Studenten 
 * Embedded Systems und Java näher zu bringen.  
 * Das Fahrzeug hat eine Doppelservolekung.  
 * Belegung:
 *  Kanal 0&1: Lenkung
 *  Kanal 2: Gas
 * 
 * Folgende Eingabegeräte werden unterstützt:
 *  JoyStick (Belegung muss ggf. in joyStickIndexToSero angepasst werden)
 *  Tastatur (Pfeiltasten, Space ist FailSafe)
 *  JSliders mit Maus
 * Steuerausschlag wird mit den Min/Max Values der JSlider eingestellt
 * 
 * FailSafe:
 *  Wenn der Arduino nach ca. 1,5 Sekunden kein Paket empfängt, so schaltet
 *  er in den FailSafe Modus.  Empfängt er dann wieder etwas, so schaltet er 
 *  zurück in den normalen Modus.
 * 
 * Rückkanal:
 *  Jedes Steuerpaket wird mit einem Statuspaket quitiert.  Dieses enthält 
 *  Messwerte des ADC, der die Akkuspannung kontrolliert.
 * 
 * Benutzung:
 *  Fahrzeug einschalten, 10 Sekunden warten bis Netzwerk aufgebaut wurde.
 *  Drahtlos-Netzwerk "Summit" verbinden (Windows)
 *  IP-Addresse eingeben
 *  Verbinden Button drücken
 *  Laufzeit kontrollieren (RoundTripTime)
 * Wenn es nicht funktioniert, test mit Ping, ob Arduino erreichbar ist.
 * Mit UMTS funktioniert der Rückkanal wegen NAT nicht.
 * Außerdem muss das SendeInterval erhöht werden (von 200ms auf 500ms)
 */

package central;

import at.wisch.joystick.event.FeatureNotSupportedEventManager;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class CommandControl extends javax.swing.JFrame {

    Icon imgicon = new ImageIcon("StopNotAus1.gif");
    private Transmitter sender = null;
    private Transmitter empfaenger = null;
    private short ADC_Values[] = null;
    public long rtt;
    //Achtung: hier werden die Failsave Values für die Servos festgelegt!
    //Lenkservo1 | Lenkservo2 | GAS | reserved
    private static short servoFailSaveValues[] = {90, 90, 92, 90};
    private static short servoMaxValues[] = {120, 120, 105, 90};
    private static short servoMinValues[] = {60, 60, 75, 90};
    private static short servoCurrentValue[] = {90, 90, 92, 90};
    private static short joyStickIndexToSero[] = {4, 4, 1, 0};
    private static double joyStickMaxValues[] = {0.70, 0.70, -0.58, 0.658};
    private static double joyStickMinValues[] = {-0.64, -0.64, 0.579};
    private static double joyStickToServo[] = {1, 1, 1, 1};
    private static JoystickControl joyStick;

    /**
     * Creates new form
     */
    public CommandControl() {
        initComponents();

        //Init Transmitters
        sender = new Transmitter(Transmitter.Mode.sender);
        servoFailSave(sender.servoState);
        empfaenger = new Transmitter(Transmitter.Mode.receiver);
        ADC_Values = empfaenger.receivedTel.ADC_Values;
        Stopp_Button.setIcon(imgicon);
        //Trennen_Button.setVisible(false);
        SendeIntervalEingabe_Textfeld.setText(empfaenger.sendInterval.toString());


        //Init Slider Listeners
        updateSliderToServoVal();
        SliderListenerDoubleServo sliderListener_Lenkung = new SliderListenerDoubleServo(0, 1);
        jSliderLenkung.addChangeListener(sliderListener_Lenkung);
        SliderListener sliderListener_Gas = new SliderListener(2);
        jSliderGas.addChangeListener(sliderListener_Gas);

        //Inititalize Timers
        java.util.Timer oneSecTimer = new java.util.Timer("oneSecTimer");
        oneSecTimer.schedule(new oneSecTimerTask(), 2000, 1000);

        java.util.Timer fastTimer = new java.util.Timer("fastTimer");
        fastTimer.schedule(new fastTimerTask(), 2000, 10);

        //Add Keylistener
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
                new KeyEventDispatcher() {

                    public boolean dispatchKeyEvent(KeyEvent e) {
                        //if (e.getID() == KeyEvent.KEY_TYPED) {
                        performKeyEvent(e);
                        //e.setKeyChar('a');
                        //}
                        boolean discardEvent = false;
                        return discardEvent;
                    }
                });


        //Add Joystick
        calcJoyStickToServo();
        joyStick = new JoystickControl();
        joyStick.start();

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        Vorwaerts_Button = new javax.swing.JButton();
        Zurueck_Button = new javax.swing.JButton();
        Links_Button = new javax.swing.JButton();
        Rechts_Button = new javax.swing.JButton();
        Stopp_Button = new javax.swing.JButton();
        jSliderLenkung = new javax.swing.JSlider();
        jSliderGas = new javax.swing.JSlider();
        jPanel2 = new javax.swing.JPanel();
        IP_Textfeld = new javax.swing.JTextField();
        Verbinden_Button = new javax.swing.JButton();
        Trennen_Button = new javax.swing.JButton();
        Test_Button = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        U_Empfang_Textfeld = new javax.swing.JTextArea();
        jPanel4 = new javax.swing.JPanel();
        jScrollPane4 = new javax.swing.JScrollPane();
        S_Empfang_Textfeld = new javax.swing.JTextArea();
        jPanel5 = new javax.swing.JPanel();
        SendeIntervalEingabe_Textfeld = new javax.swing.JTextField();
        jButton2 = new javax.swing.JButton();
        jPanel7 = new javax.swing.JPanel();
        Licht_Ein_Button = new javax.swing.JButton();
        Lichthupe_Button = new javax.swing.JButton();
        Licht_Aus_Button = new javax.swing.JButton();
        Hupe_Button = new javax.swing.JButton();
        joyText = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Mobile Sensor Platform");
        setMinimumSize(new java.awt.Dimension(627, 500));

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Steuerung", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12), java.awt.Color.darkGray)); // NOI18N
        jPanel1.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N

        Vorwaerts_Button.setText("Vor");
        Vorwaerts_Button.setToolTipText("");
        Vorwaerts_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Vorwaerts_ButtonActionPerformed(evt);
            }
        });

        Zurueck_Button.setText("Zurück");
        Zurueck_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Zurueck_ButtonActionPerformed(evt);
            }
        });

        Links_Button.setText("Links");
        Links_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Links_ButtonActionPerformed(evt);
            }
        });

        Rechts_Button.setText("Rechts");
        Rechts_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Rechts_ButtonActionPerformed(evt);
            }
        });

        Stopp_Button.setMaximumSize(new java.awt.Dimension(60, 60));
        Stopp_Button.setMinimumSize(new java.awt.Dimension(50, 50));
        Stopp_Button.setPreferredSize(new java.awt.Dimension(50, 50));
        Stopp_Button.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/central/StopNotAus1.gif"))); // NOI18N
        Stopp_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Stopp_ButtonActionPerformed(evt);
            }
        });

        jSliderLenkung.setMajorTickSpacing(10);
        jSliderLenkung.setMaximum(115);
        jSliderLenkung.setMinimum(65);
        jSliderLenkung.setMinorTickSpacing(5);
        jSliderLenkung.setPaintLabels(true);
        jSliderLenkung.setPaintTicks(true);
        jSliderLenkung.setValue(90);
        jSliderLenkung.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                jSliderLenkungMouseMoved(evt);
            }
        });
        jSliderLenkung.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                jSliderLenkungKeyTyped(evt);
            }
        });

        jSliderGas.setMajorTickSpacing(5);
        jSliderGas.setMaximum(105);
        jSliderGas.setMinimum(85);
        jSliderGas.setMinorTickSpacing(5);
        jSliderGas.setOrientation(javax.swing.JSlider.VERTICAL);
        jSliderGas.setPaintLabels(true);
        jSliderGas.setPaintTicks(true);
        jSliderGas.setToolTipText("");
        jSliderGas.setValue(92);
        jSliderGas.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                jSliderGasMouseMoved(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jSliderGas, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(Links_Button)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                    .addComponent(Vorwaerts_Button, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(Stopp_Button, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(Zurueck_Button))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(Rechts_Button))
                    .addComponent(jSliderLenkung, javax.swing.GroupLayout.PREFERRED_SIZE, 207, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {Links_Button, Rechts_Button, Stopp_Button, Vorwaerts_Button, Zurueck_Button});

        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(Vorwaerts_Button)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(Links_Button)
                            .addComponent(Rechts_Button)
                            .addComponent(Stopp_Button, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(Zurueck_Button)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jSliderLenkung, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jSliderGas, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {Links_Button, Rechts_Button, Stopp_Button, Vorwaerts_Button, Zurueck_Button});

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "IP-Address", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12), java.awt.Color.darkGray)); // NOI18N

        IP_Textfeld.setText("192.168.1.177");
        IP_Textfeld.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                IP_TextfeldActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(IP_Textfeld)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(IP_Textfeld, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 7, Short.MAX_VALUE))
        );

        Verbinden_Button.setBackground(new java.awt.Color(204, 0, 0));
        Verbinden_Button.setText("Verbinden");
        Verbinden_Button.setName("");
        Verbinden_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Verbinden_ButtonActionPerformed(evt);
            }
        });

        Trennen_Button.setText("Trennen");
        Trennen_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Trennen_ButtonActionPerformed(evt);
            }
        });

        Test_Button.setText("Test");
        Test_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Test_ButtonActionPerformed(evt);
            }
        });

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Spannungs-Werte", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12), java.awt.Color.darkGray)); // NOI18N
        jPanel3.setPreferredSize(new java.awt.Dimension(300, 140));

        U_Empfang_Textfeld.setColumns(20);
        U_Empfang_Textfeld.setRows(5);
        U_Empfang_Textfeld.setMaximumSize(new java.awt.Dimension(165, 90));
        U_Empfang_Textfeld.setMinimumSize(new java.awt.Dimension(165, 90));
        U_Empfang_Textfeld.setPreferredSize(new java.awt.Dimension(165, 90));
        jScrollPane3.setViewportView(U_Empfang_Textfeld);

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 259, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Servo-Werte", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12), java.awt.Color.darkGray)); // NOI18N
        jPanel4.setMinimumSize(new java.awt.Dimension(100, 100));
        jPanel4.setPreferredSize(new java.awt.Dimension(300, 140));

        S_Empfang_Textfeld.setColumns(20);
        S_Empfang_Textfeld.setRows(5);
        S_Empfang_Textfeld.setMaximumSize(new java.awt.Dimension(165, 90));
        S_Empfang_Textfeld.setMinimumSize(new java.awt.Dimension(165, 90));
        S_Empfang_Textfeld.setPreferredSize(new java.awt.Dimension(165, 90));
        jScrollPane4.setViewportView(S_Empfang_Textfeld);

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );

        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Sende-Interval (Ein-/Ausgabe)", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12), java.awt.Color.darkGray)); // NOI18N

        SendeIntervalEingabe_Textfeld.setText("1000");
        SendeIntervalEingabe_Textfeld.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SendeIntervalEingabe_TextfeldActionPerformed(evt);
            }
        });

        jButton2.setText("jButton2");

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(SendeIntervalEingabe_Textfeld, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addGap(1, 1, 1)
                .addComponent(jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addComponent(SendeIntervalEingabe_Textfeld)
        );

        jPanel7.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "KeineAhnung", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12), java.awt.Color.darkGray)); // NOI18N

        Licht_Ein_Button.setText("Licht EIN");
        Licht_Ein_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Licht_Ein_ButtonActionPerformed(evt);
            }
        });

        Lichthupe_Button.setText("Lichthupe");
        Lichthupe_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Lichthupe_ButtonActionPerformed(evt);
            }
        });

        Licht_Aus_Button.setText("Licht AUS");
        Licht_Aus_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Licht_Aus_ButtonActionPerformed(evt);
            }
        });

        Hupe_Button.setText("Hupe");
        Hupe_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Hupe_ButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(Licht_Ein_Button, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(Licht_Aus_Button, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(Hupe_Button, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(Lichthupe_Button, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(64, Short.MAX_VALUE))
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(Licht_Ein_Button)
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addComponent(Hupe_Button)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(Lichthupe_Button)
                            .addComponent(Licht_Aus_Button))))
                .addContainerGap(17, Short.MAX_VALUE))
        );

        joyText.setText("Joystick: empty");
        joyText.setToolTipText("Plug in a joystick to - it will be detected automatically");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 290, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(Verbinden_Button, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(Test_Button, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(Trennen_Button, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE)
                        .addComponent(jPanel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE)
                        .addComponent(jPanel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(joyText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(Verbinden_Button)
                            .addComponent(Test_Button)
                            .addComponent(Trennen_Button))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 27, Short.MAX_VALUE)
                        .addComponent(joyText)
                        .addGap(26, 26, 26)))
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );

        jPanel5.getAccessibleContext().setAccessibleName("Sende-Interval");
        jPanel7.getAccessibleContext().setAccessibleName("Tests");
        jPanel7.getAccessibleContext().setAccessibleDescription("");

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void Vorwaerts_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Vorwaerts_ButtonActionPerformed
        sender.setCMD("R");
        if (sender.servoState[2] < jSliderGas.getMaximum()) {
            sender.servoState[2] += 1;
        }
        updateSliderToServoVal();
    }//GEN-LAST:event_Vorwaerts_ButtonActionPerformed

    private void Verbinden_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Verbinden_ButtonActionPerformed
        sender.connect(IP_Textfeld.getText(), 8888);
        empfaenger.connect(IP_Textfeld.getText(), 8888);
        Verbinden_Button.setBackground(Color.green);
        Trennen_Button.setVisible(true);
    }//GEN-LAST:event_Verbinden_ButtonActionPerformed

    private void Trennen_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Trennen_ButtonActionPerformed
        sender.disconnect();
        empfaenger.disconnect();
        Verbinden_Button.setBackground(null);
    }//GEN-LAST:event_Trennen_ButtonActionPerformed

    private void Test_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Test_ButtonActionPerformed
        sender.setCMD("T");
    }//GEN-LAST:event_Test_ButtonActionPerformed

    private void Zurueck_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Zurueck_ButtonActionPerformed
        sender.setCMD("R");
        if (sender.servoState[2] > jSliderGas.getMinimum()) {
            sender.servoState[2] -= 1;
        }
        updateSliderToServoVal();
    }//GEN-LAST:event_Zurueck_ButtonActionPerformed

    private void Links_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Links_ButtonActionPerformed
        sender.setCMD("R");
        if (sender.servoState[0] > jSliderLenkung.getMinimum()) {
            sender.servoState[0] -= 3;
            sender.servoState[1] -= 3;
        }
        updateSliderToServoVal();
    }//GEN-LAST:event_Links_ButtonActionPerformed

    private void Rechts_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Rechts_ButtonActionPerformed
        sender.setCMD("R");
        if (sender.servoState[0] < jSliderLenkung.getMaximum()) {
            sender.servoState[0] += 3;
            sender.servoState[1] += 3;
        }
        updateSliderToServoVal();
    }//GEN-LAST:event_Rechts_ButtonActionPerformed

    private void Stopp_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Stopp_ButtonActionPerformed

        sender.setCMD("X");

        servoFailSave(sender.servoState);
        updateSliderToServoVal();
    }//GEN-LAST:event_Stopp_ButtonActionPerformed

    private void Hupe_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Hupe_ButtonActionPerformed
        sender.setCMD("h");
    }//GEN-LAST:event_Hupe_ButtonActionPerformed

    private void Lichthupe_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Lichthupe_ButtonActionPerformed
        sender.setCMD("f");
    }//GEN-LAST:event_Lichthupe_ButtonActionPerformed

    private void Licht_Ein_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Licht_Ein_ButtonActionPerformed
        sender.setCMD("l");
    }//GEN-LAST:event_Licht_Ein_ButtonActionPerformed

    private void Licht_Aus_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Licht_Aus_ButtonActionPerformed
        sender.setCMD("o");
    }//GEN-LAST:event_Licht_Aus_ButtonActionPerformed

    private void IP_TextfeldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_IP_TextfeldActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_IP_TextfeldActionPerformed

    private void jSliderLenkungKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jSliderLenkungKeyTyped
        sender.setCMD('R');
        sender.servoState[0] = (short) jSliderLenkung.getValue();
    }//GEN-LAST:event_jSliderLenkungKeyTyped

    private void jSliderGasMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSliderGasMouseMoved
        // TODO add your handling code here:
    }//GEN-LAST:event_jSliderGasMouseMoved

    private void jSliderLenkungMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSliderLenkungMouseMoved
        //sender.setCMD('R');
        //sender.servoState[0] = (short) jSlider1.getValue();
    }//GEN-LAST:event_jSliderLenkungMouseMoved

    private void SendeIntervalEingabe_TextfeldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SendeIntervalEingabe_TextfeldActionPerformed
        //empfaenger.sendInterval= Integer.parseInt(SendeIntervalEingabe_Textfeld.getText());       //siehe "class oneSecTimerTask"
    }//GEN-LAST:event_SendeIntervalEingabe_TextfeldActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(CommandControl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(CommandControl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(CommandControl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(CommandControl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }


        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new CommandControl().setVisible(true);


            }
        });
    }

    private void servoFailSave(short[] servoState) {
        int len = servoState.length;
        for (int i = 0; i < len; i++) {
            servoState[i] = servoFailSaveValues[i];
        }
    }

    private void updateSliderToServoVal() {
        jSliderLenkung.setValue(sender.servoState[0]);
        jSliderGas.setValue(sender.servoState[2]);
    }

    public void performKeyEvent(KeyEvent evt) {
        switch (evt.getKeyCode()) {
            case KeyEvent.VK_DOWN:
                Zurueck_ButtonActionPerformed(null);
                break;
            case KeyEvent.VK_UP:
                Vorwaerts_ButtonActionPerformed(null);
                break;
            case KeyEvent.VK_LEFT:
                Links_ButtonActionPerformed(null);
                break;
            case KeyEvent.VK_RIGHT:
                Rechts_ButtonActionPerformed(null);
                break;
            case KeyEvent.VK_SPACE:
                Stopp_ButtonActionPerformed(null);
                break;
        }
    }

    class SliderListener implements ChangeListener {

        int servo_nr = 999;

        SliderListener(int _servo_nr) {
            servo_nr = _servo_nr;
        }

        public void stateChanged(ChangeEvent e) {
            JSlider source = (JSlider) e.getSource();
            // if (!source.getValueIsAdjusting()) {
            //Fertig
            int result = source.getValue();
            sender.cmd = 'R';
            sender.servoState[servo_nr] = (short) result;
            //Empfang_Textfeld.setText("Servo "+ servo_nr +"= "+ result);
            S_Empfang_Textfeld.setText("Links/Rechts " + "            Servo = " + jSliderLenkung.getValue() + "\nVorwärts/Rückwärts " + "Servo = " + jSliderGas.getValue());
            //jLabel1.setText("Vorwärts/Rückwärts " + "Servo = " + jSliderGas.getValue());
            // } else {
            //Benutzer bewegt noch
            //  }
        }
    }

    /*
     * SliderListenerDoubleServo steuert 2 Servos mit dem selben Wert an. Die 2
     * Servonummern werden bei der Initialisierung im Konstruktor mitgegeben.
     */
    class SliderListenerDoubleServo implements ChangeListener {

        int servo_nr_1 = 999;
        int servo_nr_2 = 999;

        SliderListenerDoubleServo(int _servo_nr_1, int _servo_nr_2) {
            servo_nr_1 = _servo_nr_1;
            servo_nr_2 = _servo_nr_2;
        }

        public void stateChanged(ChangeEvent e) {
            JSlider source = (JSlider) e.getSource();
            // if (!source.getValueIsAdjusting()) {
            //Fertig
            int result = source.getValue();
            sender.cmd = 'R';
            sender.servoState[servo_nr_1] = (short) result;
            sender.servoState[servo_nr_2] = (short) result;
            //Empfang_Textfeld.setText("Servo "+ servo_nr +"= "+ result);
            S_Empfang_Textfeld.setText("Links/Rechts " + "            Servo = " + jSliderLenkung.getValue() + "\nVorwärts/Rückwärts " + "Servo = " + jSliderGas.getValue());
            //jLabel2.setText("Links/Rechts " + "            Servo = " + jSliderLenkung.getValue());

            // } else {
            //Benutzer bewegt noch
            //  }
        }
    }

    short getServoFromJoyStick(int i) {
        int joyIndex = joyStickIndexToSero[i];
        double joyValue = joyStick.channel[joyIndex];
        double servoValue = joyValue * joyStickToServo[i];
        servoValue += servoFailSaveValues[i];
        return (short) servoValue;
    }

    void calcJoyStickToServo() {
        for (int i = 0; i < servoCurrentValue.length; i++) {
            //joyStickToServo= new double[i];
            joyStickToServo[i] = (servoMaxValues[i] - servoFailSaveValues[i]) / joyStickMaxValues[i];
        }
    }

    //Update frequent Updates
    class fastTimerTask extends TimerTask {

        @Override
        public void run() {
            if (joyStick.joyStickFound > 0) {
                for (int i = 0; i < servoCurrentValue.length; i++) {
                    sender.servoState[i] = getServoFromJoyStick(i);
                }
                updateSliderToServoVal();
            }
        }
    }

    //Low Speed Updates for User Interface
    class oneSecTimerTask extends TimerTask {

        @Override
        public void run() {
            updateSliderToServoVal();
            if (joyStick.joyStickFound == 0) {
                joyText.setText("Joystick: empty");
            } else {
                joyText.setText("Joystick: " + joyStick.name);
            }

            U_Empfang_Textfeld.setText("Akku   = " + (ADC_Values[2] / 1000.0) + "V\nZelle 1 = " + ADC_Values[0] / 1000.0 + "V\nZelle 2 = " + (ADC_Values[1] - ADC_Values[0]) / 1000.0 + "V\nZelle 3 = " + (ADC_Values[2] - ADC_Values[1]) / 1000.0 + "V");

            empfaenger.sendInterval = Integer.parseInt(SendeIntervalEingabe_Textfeld.getText());     //Zeile von "private void SendeIntervalEingabe_TextfeldActionPerformed"

            rtt = empfaenger.roundTripTime;
            //jTextArea2.setText("RoundTripTime  = " + rtt);
            jButton2.setText("RoundTrip= \n" + rtt + "ms");
            //Ampel_Label.setText("RoundTripTime = " + rtt);

            if (rtt < 10) {
                jButton2.setBackground(Color.green);
                //Ampel_Label.setForeground(Color.green);
            } else if (rtt < 50) {
                jButton2.setBackground(Color.yellow);
                //Ampel_Label.setForeground(Color.yellow);
            } else if (rtt >= 50) {
                jButton2.setBackground(Color.red);
                //Ampel_Label.setForeground(Color.red);
            }

            //jTextFieldSendInterval.setText(empfaenger.sendInterval.toString());
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton Hupe_Button;
    private javax.swing.JTextField IP_Textfeld;
    private javax.swing.JButton Licht_Aus_Button;
    private javax.swing.JButton Licht_Ein_Button;
    private javax.swing.JButton Lichthupe_Button;
    private javax.swing.JButton Links_Button;
    private javax.swing.JButton Rechts_Button;
    private javax.swing.JTextArea S_Empfang_Textfeld;
    private javax.swing.JTextField SendeIntervalEingabe_Textfeld;
    private javax.swing.JButton Stopp_Button;
    private javax.swing.JButton Test_Button;
    private javax.swing.JButton Trennen_Button;
    private javax.swing.JTextArea U_Empfang_Textfeld;
    private javax.swing.JButton Verbinden_Button;
    private javax.swing.JButton Vorwaerts_Button;
    private javax.swing.JButton Zurueck_Button;
    private javax.swing.JButton jButton2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JSlider jSliderGas;
    private javax.swing.JSlider jSliderLenkung;
    private javax.swing.JLabel joyText;
    // End of variables declaration//GEN-END:variables
}
